﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.IO;
using System.Reflection;

namespace FortuneHeavenCommon.ComMethod
{
    public class ExcelGenerate
    {
        private static Page currentPage = HttpContext.Current.Handler as Page;
        private static Object sycObj = new Object();
        private static int incremental = 10;
        /// <summary>
        /// 按照时间生成excel名称 防止生成相同名的excel造成文件覆盖
        /// </summary>
        /// <returns></returns>
        private static string CreateExcelName()
        {
            lock (sycObj)
            {
                incremental = incremental + 1;
                if (incremental > 99)
                    incremental = 10;
                return Convert.ToInt64(DateTime.Now.ToString("yyyyMMddHHmmssfff") + incremental).ToString();
            }
        }
        /// <summary>
        /// 导出excel
        /// </summary>
        /// <typeparam name="T">泛型实体</typeparam>
        /// <param name="response"></param>
        /// <param name="listColumes">要显示的列名</param>
        /// <param name="listProperty">要显示的导出属性名  和实体的属性名有关,顺序由显示的列确定 可以同listColumes</param>
        /// <param name="listModel">实体集合</param>
        public static void ExportExcel<T>(HttpResponse response, IList<string> listColumns, IList<string> listProperty, IList<T> listModel) where T : class, new()
        {
            if (listColumns.Count == 0)
            {
                throw new IndexOutOfRangeException("No Columnes!");
            }
            if (listColumns.Count != listProperty.Count)
            {
                throw new ArgumentException("Columns and properties length are not equal.");
            }
            string sheetName = "sheetName";
            using (StringWriter writer = new StringWriter())
            {
                writer.WriteLine("<html xmlns:x=\"urn:schemas-microsoft-com:office:excel\">");
                writer.WriteLine("<head>");
                writer.WriteLine("<meta http-equiv=\"content-type\" content=\"application/ms-excel; charset=GB2312\"/>");
                //writer.WriteLine("<!--[if gte mso 9]>");
                //writer.WriteLine("<xml>");
                //writer.WriteLine(" <x:ExcelWorkbook>");
                //writer.WriteLine("  <x:ExcelWorksheets>");
                //writer.WriteLine("  <x:ExcelWorksheet>");
                //writer.WriteLine("    <x:Name>" + sheetName + "</x:Name>");
                //writer.WriteLine("    <x:WorksheetOptions>");
                //writer.WriteLine("      <x:Print>");
                //writer.WriteLine("      <x:ValidPrinterInfo />");
                //writer.WriteLine("      </x:Print>");
                //writer.WriteLine("    </x:WorksheetOptions>");
                //writer.WriteLine("  </x:ExcelWorksheet>");
                //writer.WriteLine("  </x:ExcelWorksheets>");
                //writer.WriteLine("</x:ExcelWorkbook>");
                //writer.WriteLine("</xml>");
                //writer.WriteLine("<!-->");
                writer.WriteLine("</head>");
                writer.WriteLine("<body>");
                writer.WriteLine("<table>");
                writer.WriteLine("<tr>");
                foreach (string item in listColumns)
                {
                    writer.WriteLine("<td>" + item + "</td>"); //列名
                }
                writer.WriteLine("</tr>");
                //通过反射 显示要显示的列
                BindingFlags bf = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static;//反射标识
                Type objType = typeof(T);
                PropertyInfo[] propInfoArr = objType.GetProperties(bf);
                foreach (T model in listModel)
                {
                    writer.WriteLine("<tr>");
                    foreach (string propName in listProperty)
                    {
                        foreach (PropertyInfo propInfo in propInfoArr)
                        {
                            if (string.Compare(propInfo.Name.ToUpper(), propName.ToUpper()) == 0)
                            {
                                PropertyInfo modelProperty = model.GetType().GetProperty(propName);
                                if (modelProperty != null)
                                {
                                    object objResult = modelProperty.GetValue(model, null);
                                    writer.WriteLine("<td>" + ((objResult == null) ? string.Empty : objResult) + "</td>");
                                }
                                else
                                {
                                    throw new Exception("Property name may be not exists!");
                                }
                            }
                        }
                    }
                    writer.WriteLine("</tr>");
                }
                writer.WriteLine("</table>");
                writer.WriteLine("</body>");
                writer.WriteLine("</html>");
                writer.Close();
                response.Clear();
                response.Buffer = true;
                response.Charset = "UTF-8";
                //currentPage.EnableViewState = false;
                response.AddHeader("Content-Disposition", "attachment; filename=" + CreateExcelName() + ".xls");
                response.ContentType = "application/ms-excel";
                response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
                response.Write(writer);
                response.End();
            }
        }
    }
}
